﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.Collections.Specialized;
using Silmoon.Reflection;

namespace Silmoon.DNS.Monitoring
{
    public class Monitor : MySilmoon.RunningAble
    {
        ArrayList ResultArray = new ArrayList();
        GBC g = null;
        Socket socket = null;
        IPEndPoint endPoint = null;
        byte[] sendData = null;
        public MonitorInfo Info { get; set; }

        public Monitor(GBC g)
        {
            this.g = g;
            this.OnStart += new OperateHandler(Monitor_OnStart);
            this.OnStop += new OperateHandler(Monitor_OnStop);
        }

        void Ready()
        {
            endPoint = new IPEndPoint(Info.Address, Info.Port);

            ///如果是HTTP GET访问，修复值
            if (Info.Type == MONITOR_TYPE.HTTPGET)
            {
                if (string.IsNullOrEmpty(Info.Param)) Info.Param = "/";
                string s = "GET " + Silmoon.Web.HttpHelper.UrlPathEncode(Info.Param, Encoding.Default) + " HTTP/1.1\r\nHOST: " + Info.Host + "\r\n\r\n";
                sendData = Encoding.Default.GetBytes(s);
            }

        }

        public void CheckOnce()
        {
            if (Info.Type == MONITOR_TYPE.HTTPGET)
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.BeginConnect((EndPoint)endPoint, AsyncConnect_OK, null);
            }
        }

        void AsyncConnect_OK(IAsyncResult i)
        {
            try
            {
                socket.EndConnect(i);
            }
            catch(Exception ex)
            {
                onFinishCheck("无法连接", -1);
                return;
            }

            socket.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, AsyncSend_OK, null);
        }
        void AsyncSend_OK(IAsyncResult i)
        {
            try
            {
                socket.EndSend(i);
            }
            catch (Exception ex)
            {
                onFinishCheck("无法连接", -1);
                return;
            }

            byte[] recvBuff = new byte[1024];
            socket.BeginReceive(recvBuff, 0, recvBuff.Length, SocketFlags.None, AsyncRecv_OK, recvBuff);
        }
        void AsyncRecv_OK(IAsyncResult i)
        {
            try
            {
                int recvLength = socket.EndReceive(i);

                string s = Encoding.Default.GetString((byte[])i.AsyncState, 0, recvLength);
                switch (Info.Type)
                {
                    case MONITOR_TYPE.DISABLED:
                        break;
                    case MONITOR_TYPE.CLOSED:
                        break;
                    case MONITOR_TYPE.HTTPGET:
                        HTTPGET_OK(s);
                        break;
                    case MONITOR_TYPE.TCPCONNECT:
                        break;
                    case MONITOR_TYPE.TCPRECV:
                        break;
                    case MONITOR_TYPE.TCPSENDRECV:
                        break;
                    default:
                        break;
                }
                socket.Close();
            }
            catch (Exception ex)
            {
                onFinishCheck("无法连接", -1);
            }
        }
        void HTTPGET_OK(string recvString)
        {
            int statecode = 0;
            try
            { statecode = int.Parse(recvString.Substring(9, 3)); }
            catch { }

            if (statecode == 0)
            {
                onFinishCheck("异常", 0);
            }
            else
            {
                onFinishCheck("正常", statecode);
            }
        }

        void onFinishCheck(string state, int statecode)
        {
            MonitorResult result = new MonitorResult();
            result.RecordOId = Info.RecordOId;
            result.State = state;
            result.StateCode = statecode;
            ResultArray.Add(result);
            if (ResultArray.Count > 10)
                ResultArray.RemoveAt(10);

            StatResult();

            g.monitorCollectController.onResultCompleted(StatResult());
        }
        MonitorResult StatResult()
        {
            ArrayList array = new ArrayList();
            NameObjectCollection collection = new NameObjectCollection();

            int max = 0;
            foreach (MonitorResult result in ResultArray)
            {
                if (collection[result.StateCode.ToString()] == null)
                {
                    StateFlag stateflag = new StateFlag();
                    stateflag.Code = 1;
                    stateflag.UserState = result;
                    collection.Add(result.StateCode.ToString(), stateflag);
                    max = 1;
                }
                else
                {
                    StateFlag stateflag = (StateFlag)collection[result.StateCode.ToString()];
                    stateflag.Code = stateflag.Code + 1;
                    collection[result.StateCode.ToString()] = stateflag;

                    if (stateflag.Code > max)
                    {
                        max = stateflag.Code;
                    }
                }
            }

            foreach (StateFlag item in collection)
            {
                if (item.Code == max)
                {
                    return (MonitorResult)item.UserState;
                }
            }
            return null;
        }

        bool Monitor_OnStop(bool success)
        {
            Abort();
            return true;
        }

        bool Monitor_OnStart(bool success)
        {
            Ready();
            return true;
        }

        public override void Dispose()
        {
            if (socket != null)
            {
                Abort();
            }
            base.Dispose();
        }

        public void Abort()
        {
            if (socket != null)
                socket.Close();
        }
    }
}
